#+PROPERTY: header-args:emacs-lisp :tangle ./init.el :mkdirp yes
This config inspired by SystemCrafters' [[https://github.com/SystemCrafters/crafted-emacs/][crafted-emacs]]
* Internals
** Store custom variables in separate file
This code simply defines path of file with contains custsom-set-variables and loads it.
#+begin_src emacs-lisp
  (setq custom-file (concat user-emacs-directory "custom.el"))
  (when (file-exists-p custom-file)
    (load custom-file))
#+end_src
** Ui customization
#+begin_src emacs-lisp
  (setq inhibit-startup-message t)

  (scroll-bar-mode -1)        ; Disable visible scrollbar
  (tool-bar-mode -1)          ; Disable the toolbar
  (tooltip-mode -1)           ; Disable tooltips
  (set-fringe-mode 0)         ; Disable fringes
  (menu-bar-mode -1)          ; Disagel menubar

  (setq visual-bell t)

  (column-number-mode)

  (setq display-line-numbers-type 'relative) ;; Display relative line numbers
  (add-hook 'prog-mode-hook #'display-line-numbers-mode) ;; Enable line numbers only when programming
#+end_src
*** Font
#+begin_src emacs-lisp
  (defvar my/default-font "JetBrains Mono")
  (defvar my/default-font-size 130)
  (defvar my/default-variable-font-size 130)

  (set-face-attribute 'default        nil :font  my/default-font   :height my/default-font-size)
  (set-face-attribute 'fixed-pitch    nil :font  my/default-font   :height my/default-font-size)
  (set-face-attribute 'variable-pitch nil :font "DejaVu Sans Mono"  :height my/default-variable-font-size)
#+end_src
** Package.el initialization
Using package.el instead of straight because I just want to install packages.
#+begin_src emacs-lisp
  (require 'package)
  (when (version< emacs-version "28")
    (add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/")))
  (add-to-list 'package-archives '("stable" . "https://stable.melpa.org/packages/"))
  (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))

  (customize-set-variable 'package-archive-priorities
			  '(("gnu"    . 99)   ; prefer GNU packages
			    ("nongnu" . 80)   ; use non-gnu packages if
					  ; not found in GNU elpa
			    ("stable" . 70)   ; prefer "released" versions
					  ; from elpa
			    ("melpa"  . 0)))  ; if all else fails, get it
					  ; from melpa
  (package-initialize)
#+end_src
** Frame opacity
Set frame opacity and ability to toggle it.
Borrowed from [[https://www.emacswiki.org/emacs/TransparentEmacs][EmacsWiki]].
#+begin_src emacs-lisp
   (defun toggle-transparency ()
     (interactive)
     (let ((alpha (frame-parameter nil 'alpha)))
       (set-frame-parameter
        nil 'alpha
        (if (eql (cond ((numberp alpha) alpha)
                       ((numberp (cdr alpha)) (cdr alpha))
                       ;; Also handle undocumented (<active> <inactive>) form.
                       ((numberp (cadr alpha)) (cadr alpha)))
                 100)
            '(85 . 50) '(100 . 100)))))
   (global-set-key (kbd "C-c t") 'toggle-transparency)
#+end_src
** Create directories automatically on file save
#+begin_src emacs-lisp
  (defadvice find-file (before make-directory-maybe (filename &optional wildcards) activate)
    "Create parent directory if not exists while visiting file."
    (unless (file-exists-p filename)
      (let ((dir (file-name-directory filename)))
        (unless (file-exists-p dir)
          (make-directory dir t)))))
#+end_src
** Do not leave autosave & backup files
Change autosave file directory
#+begin_src emacs-lisp
  (defvar auto-save-directory (expand-file-name "autosaves/" user-emacs-directory))
  (when (not (file-exists-p auto-save-directory))
    (make-directory auto-save-directory))
  (setq auto-save-file-name-transforms
    `((".*" ,auto-save-directory t)))
#+end_src
** Multiple languages
#+begin_src emacs-lisp
  (set-language-environment 'Russian)
#+end_src
** Move around windows
Windmove config is described in [[https://www.emacswiki.org/emacs/WindMove][wiki]].
#+begin_src emacs-lisp
  (global-set-key (kbd "C-c w h") 'windmove-left)
  (global-set-key (kbd "C-c w l") 'windmove-right)
  (global-set-key (kbd "C-c w k") 'windmove-up)
  (global-set-key (kbd "C-c w j") 'windmove-down)
#+end_src
* Package
** Use-package
[[https://github.com/jwiegley/use-package][Use-package]] helps simplify .emacs file
#+begin_src emacs-lisp
  ;; No need to put :ensure t
  (unless (package-installed-p 'use-package)
    (package-refresh-contents)
    (package-install 'use-package))
  (require 'use-package)
  (setq use-package-always-ensure t)
#+end_src
** Elpa keyring updated
Import gpg keys from elpa to avoid bad signatures
#+begin_src emacs-lisp :tangle yes
(use-package gnu-elpa-keyring-update)
#+end_src
** Meow (Modal editing)
[[https://github.com/meow-edit/meow/][Meow]] brings to emacs new way of modal editing similar to Kakoune's
*** Meow keymap
Define meow keymap for qwerty layout
#+begin_src emacs-lisp
  (defun meow-setup ()
    (setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty)
    (meow-motion-overwrite-define-key
     '("j" . meow-next)
     '("k" . meow-prev)
     '("<escape>" . ignore))
    (meow-leader-define-key
     ;; SPC j/k will run the original command in MOTION state.
     '("j" . "H-j")
     '("k" . "H-k")
     ;; Use SPC (0-9) for digit arguments.
     '("1" . meow-digit-argument)
     '("2" . meow-digit-argument)
     '("3" . meow-digit-argument)
     '("4" . meow-digit-argument)
     '("5" . meow-digit-argument)
     '("6" . meow-digit-argument)
     '("7" . meow-digit-argument)
     '("8" . meow-digit-argument)
     '("9" . meow-digit-argument)
     '("0" . meow-digit-argument)
     '("/" . meow-keypad-describe-key)
     '("?" . meow-cheatsheet))
    (meow-normal-define-key
     '("0" . meow-expand-0)
     '("9" . meow-expand-9)
     '("8" . meow-expand-8)
     '("7" . meow-expand-7)
     '("6" . meow-expand-6)
     '("5" . meow-expand-5)
     '("4" . meow-expand-4)
     '("3" . meow-expand-3)
     '("2" . meow-expand-2)
     '("1" . meow-expand-1)
     '("-" . negative-argument)
     '(";" . meow-reverse)
     '("," . meow-inner-of-thing)
     '("." . meow-bounds-of-thing)
     '("[" . meow-beginning-of-thing)
     '("]" . meow-end-of-thing)
     '("a" . meow-append)
     '("A" . meow-open-below)
     '("b" . meow-back-word)
     '("B" . meow-back-symbol)
     '("c" . meow-change)
     '("d" . meow-delete)
     '("D" . meow-backward-delete)
     '("e" . meow-next-word)
     '("E" . meow-next-symbol)
     '("f" . meow-find)
     '("g" . meow-cancel-selection)
     '("G" . meow-grab)
     '("h" . meow-left)
     '("H" . meow-left-expand)
     '("i" . meow-insert)
     '("I" . meow-open-above)
     '("j" . meow-next)
     '("J" . meow-next-expand)
     '("k" . meow-prev)
     '("K" . meow-prev-expand)
     '("l" . meow-right)
     '("L" . meow-right-expand)
     '("m" . meow-join)
     '("n" . meow-search)
     '("o" . meow-block)
     '("O" . meow-to-block)
     '("p" . meow-yank)
     '("q" . meow-quit)
     '("Q" . meow-goto-line)
     '("r" . meow-replace)
     '("R" . meow-swap-grab)
     '("s" . meow-kill)
     '("t" . meow-till)
     '("u" . meow-undo)
     '("U" . meow-undo-in-selection)
     '("v" . meow-visit)
     '("w" . meow-mark-word)
     '("W" . meow-mark-symbol)
     '("x" . meow-line)
     '("X" . meow-goto-line)
     '("y" . meow-save)
     '("Y" . meow-sync-grab)
     '("z" . meow-pop-selection)
     '("'" . repeat)
     '("<escape>" . ignore)))
#+end_src

*** Meow package
#+begin_src emacs-lisp
  (use-package meow
    :config
    (meow-setup)
    (meow-global-mode 1))
#+end_src
** Doom UI
*** Doom themes
[[https://github.com/doomemacs/theme][Doom-themes]] is collection of cool themes that I like.
#+begin_src emacs-lisp
  (use-package doom-themes
    :config
    ;; Global settings (defaults)
    (setq doom-themes-enable-bold t    ; if nil, bold is universally disabled
          doom-themes-enable-italic t) ; if nil, italics is universally disabled
    (load-theme 'doom-monokai-classic t)

    ;; Enable flashing mode-line on errors
    (doom-themes-visual-bell-config)
    ;; Enable custom neotree theme (all-the-icons must be installed!)
    ;;(doom-themes-neotree-config)
    ;; or for treemacs users
    ;;(setq doom-themes-treemacs-theme "doom-atom") ; use "doom-colors" for less minimal icon theme
    ;;(doom-themes-treemacs-config)
    ;; Corrects (and improves) org-mode's native fontification.
    (doom-themes-org-config))
#+end_src
*** Dom modeline
#+begin_src emacs-lisp
  (use-package all-the-icons)

  (use-package doom-modeline
    :init (doom-modeline-mode 1))
#+end_src
** Org
*** Improve font faces
Sometimes using =variable-pitch= font anin't good.
#+begin_src emacs-lisp
  (use-package org-faces
    :ensure nil
    :after org
    :custom-face
    (org-block           ((nil (:inherit fixed-pitch :foreground nil))))
    (org-code            ((nil (:inherit (shadow fixed-pitch)))))
    (org-table           ((nil (:inherit fixed-pitch))))
    (org-verbatim        ((nil (:inherit (shadow fixed-pitch)))))
    (org-special-keyword ((nil (:inherit (font-lock-comment-face fixed-pitch)))))
    (org-meta-line       ((nil (:inherit (font-lock-comment-face fixed-pitch)))))
    (org-checkbox        ((nil (:inherit fixed-pitch)))))
#+end_src

*** Base config
#+begin_src emacs-lisp
  (defun my/org-mode-setup ()
    (org-indent-mode)
    (org-hide-block-all) ;; Collapse all blocks
    (variable-pitch-mode 1)
    (visual-line-mode 1))

  (use-package org
    :hook (org-mode . my/org-mode-setup))
#+end_src

*** Nicer org bullets
[[https://github.com/integral-dw/org-superstar-mode][Org-superstar]] is providing nice org mode symbols
#+begin_src emacs-lisp
  (use-package org-superstar
    :after org
    :hook (org-mode . (lambda () (org-superstar-mode 1))))
#+end_src
*** Center org buffer
[[https://codeberg.org/joostkremers/visual-fill-column][Visual-fill-column]] is used to center the org buffer
#+begin_src emacs-lisp
  (defun my/org-mode-visual-fill ()
    (setq visual-fill-column-width 120
          visual-fill-column-center-text t)
    (visual-fill-column-mode 1))

  (use-package visual-fill-column
    :after org
    :hook (org-mode . my/org-mode-visual-fill))
#+end_src


** Completion
*** Corfu
[[https://github.com/minad/corfu][Corfu]] deals auto-completion popup.
#+begin_src emacs-lisp
  (use-package corfu
    :custom
    (corfu-auto t)
    (corfu-separator ?\s)
    (corfu-quit-no-match 'separator)
    :init
    (global-corfu-mode)
    :bind (:map corfu-map	([remap isearch-forward] . corfu-insert-separator)))
#+end_src
**** Complementary config
#+begin_src emacs-lisp
  (use-package emacs
    :init
    (setq tab-always-indent 'complete))
#+end_src
****  Corfu-popupinfo
#+begin_src emacs-lisp
  (use-package corfu-popupinfo
    :ensure nil
    :after corfu
    :custom
    (corfu-popupinfo-delay 0)
    :init
    (corfu-popupinfo-mode)
    :bind (:map corfu-popupinfo-map
          ("M-p" . corfu-popupinfo-scroll-down)
          ("M-n" . corfu-popupinfo-scroll-up)))
#+end_src
****  Kind icon
[[https://github.com/jdtsmith/kind-icon][Kind-icon]] provides nice icons for corfu popup
#+begin_src emacs-lisp
  (use-package kind-icon
  :ensure t
  :after corfu
  :custom
  (kind-icon-use-icons nil)
  (kind-icon-default-face 'corfu-default) ; to compute blended backgrounds correctly
  :config
  (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))
#+end_src

*** Orderless
[[https://github.com/oantolin/orderless][Orderlsess]] is a new completion system
#+begin_src emacs-lisp
    (use-package orderless
      :custom
      (completion-styles '(orderless basic))
      (completion-category-defaults nil)
      (completion-category-overrides '((file (styles basic partial-completion))
                                       (eglot (styles orderless)))))
#+end_src
*** Cape
[[https://github.com/minad/cape][Cape]] adds capfs to corfu
#+begin_src emacs-lisp
  (use-package cape
    :init
    (dolist (capf (list #'cape-dabbrev
                        #'cape-file))
      (add-to-list 'completion-at-point-functions capf)))
#+end_src

*** Yasnippet
Add some nice snippets
#+begin_src emacs-lisp
  (use-package yasnippet
    :diminish
    :config
    (yas-reload-all)
    (yas-global-mode))

  (use-package yasnippet-snippets)

  (use-package company)

  (use-package company-yasnippet
    :ensure nil
    :config
    (add-to-list 'completion-at-point-functions (cape-company-to-capf #'company-yasnippet)))
#+end_src

*** Vertico
[[https://github.com/minad/vertico][Vertico]] provides interactive completion ui
#+begin_src emacs-lisp
  (use-package vertico
    :init (vertico-mode))

  ;; Persist history over Emacs restarts. Vertico sorts by history position.
  (use-package savehist
    :init
    (savehist-mode))

  ;; A few more useful configurations...
  (use-package emacs
    :init
    ;; Add prompt indicator to `completing-read-multiple'.
    ;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
    (defun crm-indicator (args)
      (cons (format "[CRM%s] %s"
                    (replace-regexp-in-string
                     "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
                     crm-separator)
                    (car args))
            (cdr args)))
    (advice-add #'completing-read-multiple :filter-args #'crm-indicator)

    ;; Do not allow the cursor in the minibuffer prompt
    (setq minibuffer-prompt-properties
          '(read-only t cursor-intangible t face minibuffer-prompt))
    (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)

    ;; Emacs 28: Hide commands in M-x which do not work in the current mode.
    ;; Vertico commands are hidden in normal buffers.
    ;; (setq read-extended-command-predicate
    ;;       #'command-completion-default-include-p)

    ;; Enable recursive minibuffers
    (setq enable-recursive-minibuffers t))
#+end_src
**** Vertico directory
#+begin_src emacs-lisp
  (use-package vertico-directory
    :after vertico
    :ensure nil
    :bind (:map vertico-map
                ("RET" . vertico-directory-enter)
                ("DEL" . vertico-directory-delete-char)
                ("M-DEL" . vertico-directory-delete-word))
    :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
#+end_src
****  Marginilia
[[https://github.com/minad/marginalia][Marginilia]] enables rich buffer annotations
#+begin_src emacs-lisp
  (use-package marginalia
    ;; Either bind `marginalia-cycle' globally or only in the minibuffer
    :bind (("M-A" . marginalia-cycle)
           :map minibuffer-local-map
           ("M-A" . marginalia-cycle))

    ;; The :init configuration is always executed (Not lazy!)
    :init

    ;; Must be in the :init section of use-package such that the mode gets
    ;; enabled right away. Note that this forces loading the package.
    (marginalia-mode))
#+end_src

*** Eglot
[[https://github.com/joaotavora/eglot][Eglot]] is like lsp but more lightweight
#+begin_src emacs-lisp
  (defun my/eglot-capf ()
    (setq-local completion-at-point-functions
                (list (cape-super-capf
                       #'eglot-completion-at-point
                       (cape-company-to-capf #'company-yasnippet)
                       #'cape-dabbrev
                       #'cape-file))))
  (use-package eglot
    :config
    (advice-add 'eglot-completion-at-point :around #'cape-wrap-buster)
    :bind (("C-c l a a" . eglot-code-actions)
           ("C-c l a i" . eglot-code-actions-inline)
           ("C-c l a q" . eglot-code-actions-quickfix)
           ("C-c l a e" . eglot-code-actions-extract)
           ("C-c l a r" . eglot-code-actions-rewrite)
           ("C-c l r" . elot-rename)
           ("C-c l s d" . xref-find-definitions)
           ("C-c l s i" . eglot-find-implementation)
           ("C-c l s c" . eglot-find-declaration)
           ("C-c l s t" . eglot-find-typeDefinition))

    :hook
    (eglot-managed-mode . my/eglot-capf))
#+end_src
** Magit
[[https://magit.vc/][Magit]] provides git integration
#+begin_src emacs-lisp
  (use-package magit)
#+end_src
** Helpful
[[https://github.com/Wilfred/helpful][Heplful]] profives better documentation for emacs
#+begin_src emacs-lisp
  (use-package helpful
    :bind
    (([remap describe-function] . helpful-callable)
     ([remap describe-variable] . helpful-variable)
     ([remap describe-key]      . helpful-key)
     ([remap describe-command]  . helpful-command)))
#+end_src
** Do not liter
Do not leave litter files
#+begin_src emacs-lisp
  (use-package no-littering
    :init
    (setq no-littering-etc-directory
          (expand-file-name "config/" user-emacs-directory))
    (setq no-littering-var-directory
          (expand-file-name "data/" user-emacs-directory))
    (setq backup-directory-alist
          `(("\\`/tmp/" . nil)
            ("\\`/dev/shm/" . nil)
            ("." . ,(no-littering-expand-var-file-name "backup/")))))
#+end_src
** Languages
Language-specific configurations
*** Fish
#+begin_src emacs-lisp
  (use-package fish-mode)
#+end_src
*** Haskell
#+begin_src emacs-lisp
  (use-package haskell-mode)
#+end_src
*** Clojure
#+begin_src emacs-lisp
  (use-package clojure-mode)
#+end_src

**** Cider
[[https://github.com/clojure-emacs/cider][Cider]] brings REPL driven clojure develpment to clojure in emacs.
#+begin_src emacs-lisp
  (use-package cider)
#+end_src

**** Clj-refactor
[[https://github.com/clojure-emacs/clj-refactor.el][Clj-refactor]] provides powerful refactoring functionality for Clojure projects.
#+begin_src emacs-lisp
  (defun my/clojure-mode-hook ()
      (clj-refactor-mode 1)
      (yas-minor-mode 1) ; for adding require/use/import statements
      ;; This choice of keybinding leaves cider-macroexpand-1 unbound
      (cljr-add-keybindings-with-prefix "C-c C-m"))
  (use-package clj-refactor
    :hook (clojure-mode . my/clojure-mode-hook))
#+end_src

** Telega.el
[[https://github.com/zevlg/telega.el][Telega]] enables telegram integration.
Requires [[https://github.com/tdlib/td][tdlib]].
#+begin_src emacs-lisp
  (use-package telega)
#+end_src
